<?php
// use \Phalcon\Di\FactoryDefault;
use enums\HttpServerEnums;
use libraries\CommUtils;
use enums\ServiceEnums;

class HttpServer
{
	public static $instance;

// 	public $http;
// 	public static $get;
// 	public static $post;
// 	public static $header;
// 	public static $server;
	public static $response;
// 	public static $session;
	public static $cookie;
	
	private $application;
// 	private $di;
	
	public function __construct() 
	{
		$http = new swoole_http_server( "0.0.0.0", 9501);

		$http->set(
			array(
				'worker_num' => 4,
				'daemonize' => false,
	            'max_request' => 0,
// 	            'dispatch_mode' => 3,
// 				'heartbeat_check_interval' => 5,
// 				'heartbeat_idle_time' => 10,
				//'tcp_defer_accept' => 5,
// 				'enable_reuse_port' => true, //3.9内核以上支持
// 				'task_worker_num' => 16,
// 				'log_file' => '/var/log/swoole/swoole.log'
			)
		);

		$http->on('WorkerStart' , array( $this , 'onWorkerStart'));

		//version < 1.8.6
		if( version_compare( SWOOLE_VERSION, '1.8.6' ) < 0 )
		{
			$http->setGlobal( HTTP_GLOBAL_ALL );
		}
		
		$http->on( 'Start', function( $serv ){
			echo 'Starting...' . PHP_EOL;
			if( php_uname('s') != 'Darwin' )
			{
				cli_set_process_title( 'reload_master' );
			}
		});
		
		$http->on('request', function ($request, $response) use ($http){
			
			register_shutdown_function(array($this, 'handleFatal'));
			
			//--------------------------------------
			//version >= 1.8.6 
			
			if( version_compare( SWOOLE_VERSION, '1.8.6' ) >= 0 )
			{
				$this->fillGlobalVal( $request, $response );
			}
			
			HttpServer::$response = $response;

			$sid = $this->application->session;
				
			if( isset( $request->cookie[ HttpServerEnums::SESSION_KEY ] ))
			{
// 				if( isset( $request->cookie ) )
					$_COOKIE = $request->cookie;
				
				$sid->setId( $request->cookie[ HttpServerEnums::SESSION_KEY ] );
			}
			else
			{
// 				$strSessionID = '' . sprintf( '%04X%04X%04X%04X%04X%04X%04X%04X', mt_rand(0, 65535), mt_rand(0, 65535),
// 						mt_rand(0, 65535), mt_rand(16384, 20479), mt_rand(32768, 49151),
// 						mt_rand(0, 65535), mt_rand(0, 65535), mt_rand(0, 65535) );
			
				$strSessionID = CommUtils::getUUIDNoDash();
				
				$sid->setId( $strSessionID );
				
				$cookies = $this->application->di->get( ServiceEnums::SERVICE_COOKIES );
				$cookies->set( HttpServerEnums::SESSION_KEY , $strSessionID, 0, '/' );
				
				$_SERVER[ 'HTTP_COOKIE' ] = HttpServerEnums::SESSION_KEY . '='. $strSessionID . ';';
				$_COOKIE[ HttpServerEnums::SESSION_KEY ] = $strSessionID;
				
			}

			if( empty( $request->server[ 'path_info' ] ))
			{
				$response->end( 'error request no path_info!<br>' );
			
				return;
			}
			
// 			$strHtml = include APP_ROOT . 'server/reconnect.php';
			$strHtml = $this->application->handle( $request->server[ 'path_info' ])->getContent();
				
			$response->gzip( 1 );
		  	$response->end( $strHtml );
		});
		
		$http->start();
		
	}

	private function fillGlobalVal( $request, $response )
	{
		if( isset($request->server) || isset( $request->header ))
		{//set server
// 			$_SERVER = null;
			unset( $_SERVER );
			$_SERVER = array();
			
			$_SERVER = array_merge( $_SERVER, array_change_key_case( $request->server, CASE_UPPER ));
			$_SERVER = array_merge( $_SERVER, array_change_key_case( $request->header, CASE_UPPER ));
			
//   no     $_SERVER[ 'REDIRECT_STATUS' ] = isset( $_SERVER[ 'status' ] ) ? $_SERVER[ 'status' ] : null;
			$_SERVER[ 'HTTP_HOST' ] = isset( $_SERVER[ 'HOST' ] ) ? $_SERVER[ 'HOST' ] : null;
			$_SERVER[ 'HTTP_USER_AGENT' ] = isset( $_SERVER[ 'USER-AGENT' ] ) ? $_SERVER[ 'USER-AGENT' ] : null;
			$_SERVER[ 'HTTP_ACCEPT' ] = isset( $_SERVER[ 'ACCEPT' ] ) ? $_SERVER[ 'ACCEPT' ] : null;
			$_SERVER[ 'HTTP_ACCEPT_LANGUAGE' ] = isset( $_SERVER[ 'ACCEPT-LANGUAGE' ] ) ? $_SERVER[ 'ACCEPT-LANGUAGE' ] : null;
			$_SERVER[ 'HTTP_ACCEPT_ENCODING' ] = isset( $_SERVER[ 'ACCEPT_ENCODING' ] ) ? $_SERVER[ 'ACCEPT-ENCODING' ] : null;
			$_SERVER[ 'HTTP_REFERER' ] = isset( $_SERVER[ 'REFERER' ] ) ? $_SERVER[ 'REFERER' ] : null;
			
			if( isset( $request->cookie ))
			{
				$strCookie = '';
				foreach( $request->cookie as $k => $v)
				{
					$strCookie = $k . '=' . $v . ';';
				}
			}
			
			$_SERVER[ 'HTTP_COOKIE' ] = isset( $strCookie ) ? $strCookie : null; 
			
			$_SERVER[ 'HTTP_CONNECTION' ] = isset( $_SERVER[ 'CONNECTION' ] ) ? $_SERVER[ 'CONNECTION' ] : null;
			
			$_SERVER[ 'HTTP_UPGRADE_INSECURE_REQUESTS' ] = isset( $_SERVER[ 'UPGRADE-INSECURE-REQUESTS' ] ) ? $_SERVER[ 'UPGRADE-INSECURE-REQUESTS' ] : null;
			$_SERVER[ 'HTTP_CACHE_CONTROL' ] = isset( $_SERVER[ 'CACHE-CONTROL' ] ) ? $_SERVER[ 'CACHE-CONTROL' ] : null;
			$_SERVER[ 'CONTENT_TYPE' ] = isset( $_SERVER[ 'CONTENT-TYPE' ] ) ? $_SERVER[ 'CONTENT-TYPE' ] : null;
			$_SERVER[ 'CONTENT_LENGTH' ] = isset( $_SERVER[ 'CONTENT-LENGTH' ] ) ? $_SERVER[ 'CONTENT-LENGTH' ] : null;

			$_SERVER[ 'HTTP_X_REQUESTED_WITH' ] = isset( $_SERVER[ 'X-REQUESTED-WITH' ] ) ? $_SERVER[ 'X-REQUESTED-WITH' ] : null;
//no		$_SERVER[ 'PATH' ] = isset( $_SERVER[ 'USER-AGENT' ];

// 	no		$_SERVER[ 'DYLD_LIBRARY_PATH' ] = isset( $_SERVER[ 'USER-AGENT' ];
// 	no		$_SERVER[ 'SERVER_SIGNATURE' ] = isset( $_SERVER[ 'USER-AGENT' ];

// 	same	$_SERVER[ 'SERVER_SOFTWARE' ] = isset( $_SERVER[ 'SERVER_SOFTWARE' ];
// 	no		$_SERVER[ 'SERVER_NAME' ] = isset( $_SERVER[ 'USER-AGENT' ];
// 	no		$_SERVER[ 'SERVER_ADDR' ] = isset( $_SERVER[ 'USER-AGENT' ];
// 	same		$_SERVER[ 'SERVER_PORT' ] = isset( $_SERVER[ 'USER-AGENT' ];
// 	same		$_SERVER[ 'REMOTE_ADDR' ] = isset( $_SERVER[ 'USER-AGENT' ];
// 	same		$_SERVER[ 'REMOTE_PORT' ] = isset( $_SERVER[ 'USER-AGENT' ];

// 	no		$_SERVER[ 'DOCUMENT_ROOT' ] = isset( $_SERVER[ 'USER-AGENT' ];
// 	no		$_SERVER[ 'REQUEST_SCHEME' ] = isset( $_SERVER[ 'USER-AGENT' ];
// no			$_SERVER[ 'CONTEXT_PREFIX' ] = isset( $_SERVER[ 'USER-AGENT' ];
// no			$_SERVER[ 'CONTEXT_DOCUMENT_ROOT' ] = isset( $_SERVER[ 'USER-AGENT' ];
// no			$_SERVER[ 'SERVER_ADMIN' ] = isset( $_SERVER[ 'USER-AGENT' ];
// no			$_SERVER[ 'SCRIPT_FILENAME' ] = isset( $_SERVER[ 'USER-AGENT' ];
// no			$_SERVER[ 'REDIRECT_URL' ] = isset( $_SERVER[ 'USER-AGENT' ];
// no			$_SERVER[ 'REDIRECT_QUERY_STRING' ] = isset( $_SERVER[ '' ];
// no			$_SERVER[ 'GATEWAY_INTERFACE' ] = isset( $_SERVER[ 'USER-AGENT' ];
// same			$_SERVER[ 'SERVER_PROTOCOL' ] = isset( $_SERVER[ 'USER-AGENT' ];
// same			$_SERVER[ 'REQUEST_METHOD' ] = isset( $_SERVER[ 'USER-AGENT' ];
// same			$_SERVER[ 'QUERY_STRING' ] = isset( $_SERVER[ 'QUERY_STRING' ] ) ? $_SERVER[ 'QUERY_STRING' ] : null;
// same		$_SERVER[ 'REQUEST_URI' ] = isset( $_SERVER[ 'USER-AGENT' ];REQUEST_URI
//no 		$_SERVER[ 'SCRIPT_NAME' ] = isset( $_SERVER[ 'USER-AGENT' ];
//no 			$_SERVER[ 'PHP_SELF' ] = isset( $_SERVER[ 'USER-AGENT' ];
// 	same		$_SERVER[ 'REQUEST_TIME_FLOAT' ] = isset( $_SERVER[ 'USER-AGENT' ];
// 	same		$_SERVER[ 'REQUEST_TIME' ] = isset( $_SERVER[ 'USER-AGENT' ];
			
		}
		else
		{
			$_SERVER = [];
		}
			
		//set $_GET
		if( isset($request->get) )
		{
			$_GET = $request->get;
			$_GET[ '_uri' ] = $request->server[ 'request_uri' ];
		}
// 			var_dump( $request );
			
		//set post	
		if( isset( $request->post ) ) 
		{
			$_POST = $request->post;
		}
		
// 		if( isset( $request->files))
		
		//SET REQUEST
		$_REQUEST = array_merge( $_GET, $_POST );
	}
	
	public function onWorkerStart() 
	{
		echo __FUNCTION__, PHP_EOL, PHP_EOL;
		if( PHP_OS == 'Linux' )
		{
			$user = posix_getpwnam( 'nobody' );
			posix_setgid( $user['gid']);
			posix_setuid( $user['uid']);
		}
		
		
		error_reporting( E_ALL );
		ini_set( 'display_errors', '1' );
		
		define( 'APP_ROOT', dirname( __DIR__ ) . '/' );
		define( 'APP_MODE', 'dev' );
		
		//将出错信息输出到一个文本文件
		ini_set( 'error_log', APP_ROOT . '/logs/php_error_log.txt' );
		
		
		
		$loader = new \Phalcon\Loader();
		$loader->registerNamespaces( array(
			'libraries' => APP_ROOT . 'libraries/',
			'utils'		=> APP_ROOT . 'apps/utils/',
			'apis'		=> APP_ROOT . 'apis',
			'enums'		=> APP_ROOT . 'enums/',
			'listeners'	=> APP_ROOT . 'listeners/',
		    'vendors'   => APP_ROOT . 'vendors/'
		));
		$loader->register();
		
		
		$di = new \Phalcon\DI\FactoryDefault();
		$arrInitCfg = array(
			array( 'name' => 'lockCfg', 'file' => 'lock.php', 'inDi' => true ),
			array( 'name' => 'sessionCfg', 'file' => 'session.php', 'inDi' => true ),
			array( 'name' => 'urlCfg', 'file' => 'url.php', 'inDi' => true ),
			array( 'name' => 'dbCfg', 'file' => 'db.php', 'inDi' => true ),
			array( 'name' => 'queueCfg', 'file' => 'queue.php', 'inDi' => true ),
			array( 'name' => 'config', 'file' => 'config.php', 'inDi' => true ),
			array( 'name' => 'logCfg', 'file' => 'log.php', 'inDi' => true ),
			array( 'name' => 'cacheCfg', 'file' => 'cache.php', 'inDi' => true ),
			array( 'name' => 'emailCfg', 'file' => 'email.php', 'inDi' => true ),
		);
		
		//set in di
		foreach( $arrInitCfg as $cfg )
		{
			if( file_exists( APP_ROOT . 'config/' . APP_MODE . '/' . $cfg[ 'file' ] ))
			{
				if( $cfg[ 'inDi' ] )
				{
					$di->set( $cfg['name'], require APP_ROOT . 'config/' . APP_MODE . '/' . $cfg['file'], true );
				}
				else
				{
					${$cfg[ 'name' ]} = require APP_ROOT . 'config/' . APP_MODE . '/' . $cfg['file'];
				}
			}
			else
			{
				if( $cfg[ 'inDi' ] )
				{
					$di->set( $cfg['name'], require APP_ROOT . 'config/' . $cfg['file'], true );
				}
				else
				{
					${$cfg[ 'name' ]} = require APP_ROOT . 'config/' . $cfg['file'];
				}
			}
		}
		
		
		
		require APP_ROOT . 'config/services.php';//加载公共services
		
		$this->application = new \Phalcon\Mvc\Application($di);
		
		// Register the installed modules
		$this->application->registerModules( array(
	        'common' => 
			array(
	            'className' => 'apps\common\Module',
	            'path' => APP_ROOT . 'apps/common/Module.php'
	        ),
	        'fzq' => 
	        array(
	    		'className' => 'apps\fzq\Module',
	    		'path' => APP_ROOT . 'apps/fzq/Module.php'
	        )
		       
		));
		

	}

	public static function getInstance() 
	{
		if (!self::$instance) {
            self::$instance = new HttpServer;
        }
        return self::$instance;
	}
	
	public function handleFatal()
	{
		$error = error_get_last();
		
		if (isset($error['type'])) 
		{
			switch ($error['type']) 
			{
				case E_ERROR:
				case E_PARSE:
				case E_CORE_ERROR:
				case E_COMPILE_ERROR:
					$message = $error['message'];
					$file    = $error['file'];
					$line    = $error['line'];
					$log     = "$message ($file:$line)\nStack trace:\n";
					$trace   = debug_backtrace();
					
					foreach ($trace as $i => $t) 
					{
						if (!isset($t['file'])) 
						{
							$t['file'] = 'unknown';
						}
						
						if (!isset($t['line'])) 
						{
							$t['line'] = 0;
						}
						
						if (!isset($t['function'])) 
						{
							$t['function'] = 'unknown';
						}
						
						$log .= "#$i {$t['file']}({$t['line']}): ";
						
						if (isset($t['object']) and is_object($t['object'])) 
						{
							$log .= get_class($t['object']) . '->';
						}
						$log .= "{$t['function']}()\n";
					}
					
					if (isset($_SERVER['REQUEST_URI'])) 
					{
						$log .= '[QUERY] ' . $_SERVER['REQUEST_URI'];
					}

					self::$response->end( $log );
// 					$this->application->logger->info('error log: ' . $log);
// 					self::$response->status( 500 );
// 					self::$response->end( 'Internal Server Errors' );
					
				default:
					break;
			}
		}
	}
}

HttpServer::getInstance();
